//
//  CCMNetworkLoggerPlugin.swift
//  CCMoney_swift
//
//  Created by JKHuang on 2018/11/27.
//  Copyright © 2018 JKHuang. All rights reserved.
//

import UIKit
import Moya
import Result
import SVProgressHUD

class CCMNetworkLoggerPlugin: PluginType {

    func willSend(_ request: RequestType, target: TargetType) {
        
    }
    
    func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) {
        print("=========================== Network start ============================")
        
        switch result {
        case .success(let response):
            outputItems(logNetworkRequest(response.request))
            outputItems(logNetworkResponse(response.response, data: response.data, target: target))
        case .failure(let error):
            outputItems(logNetworkRequest(error.response?.request))
            outputItems(logNetworkResponse(nil, data: nil, target: target))
        }
        
        print("============================ Network End =============================")
    }
    
    fileprivate func outputItems(_ items: [String]) {
        for string in items {
            print("\(string)\n")
        }
    }
}

private extension CCMNetworkLoggerPlugin {
    
    func format(identifier: String, message: String) -> String {
        return "\(identifier): \(message)"
    }
    
    func logNetworkRequest(_ request: URLRequest?) -> [String] {
        
        var output = [String]()
        
        output += [format(identifier: "Request URL", message: request?.url?.absoluteString ?? "(invalid request)")]
        
        if let httpMethod = request?.httpMethod {
            output += [format(identifier: "HTTP Request Method", message: httpMethod)]
        }
        
        if let headers = request?.allHTTPHeaderFields {
            output += [format(identifier: "Request Headers", message: headers.description)]
        }
        
        if let bodyStream = request?.httpBodyStream {
            output += [format(identifier: "Request Body Stream", message: bodyStream.description)]
        }
        
        if let body = request?.httpBody, let stringOutput = String(data: body, encoding: .utf8) {
            output += [format(identifier: "Request Body", message: stringOutput)]
        }
        
        return output
    }
    
    func logNetworkResponse(_ response: HTTPURLResponse?, data: Data?, target: TargetType) -> [String] {
        if response == nil {
            return [format(identifier: "Response", message: "Received empty network response for \(target).")]
        }
        
        var output = [String]()
        
        if let data = data, let stringData = String(data: data, encoding: String.Encoding.utf8) {
            output += [format(identifier: "ResponseData", message: stringData)]
        }
        
        return output
    }
}

